import groovy.xml.StreamingMarkupBuilder
class VaadinGrailsPlugin {
    def VAADIN_CONFIG_FILE = "VaadinConfig"

    // the plugin version
    def version = "1.0"
    // the version or versions of Grails the plugin is designed for
    def grailsVersion = "1.1.1 > *"
    // the other plugins this plugin depends on
    def dependsOn = [:]
    // resources that are excluded from plugin packaging
    def pluginExcludes = [
            "grails-app/views/error.gsp"
    ]
    
    def author = "Daniel Bell"
    def authorEmail = "daniel.r.bell@gmail.com"
    def title = "Vaadin Grails Plugin"
    def description = '''
        A plugin for creating a Vaadin application on Grails. This plugin will
    automatically enable an application to specify a Vaadin Application class
    from which the application will start.
        After installing the plugin:
    1) Create a class that extends com.vaadin.Application
    2) Specify this class in the Vaadin configuration file
        (grails-app/conf/VaadinConfig.groovy)
    3) Remove the URL mappings for the URL where you want to access the
        Vaadin application.
    3) Execute grails run-app
    '''

    // URL to the plugin's documentation
    def documentation = "http://vaadin.com"
//    def watchedResources = ["**/grails-app/conf/${VAADIN_CONFIG_FILE}.groovy"]


    def doWithSpring = {
        // TODO Add Spring beans if required
    }

    def doWithApplicationContext = { applicationContext ->
        // TODO Implement post initialization spring config (optional)
    }

    def doWithWebDescriptor = { webXml ->
        def config = getConfig()
        if(!config || !(config.applicationClass)){
            return
        }

        def vaadinApplicationClass = config.applicationClass
        def vaadinProductionMode = config.productionMode

        def contextParams = webXml."context-param"
        contextParams[contextParams.size() - 1] +  {
                        "context-param" {
                            "description"("Vaadin production mode")
                            "param-name"("productionMode")
                            "param-value"(vaadinProductionMode)
            }
        }

        def servlets = webXml."servlet"
        servlets[servlets.size() - 1] +  {
                    "servlet" {
                            "servlet-name"("VaadinServlet")
                            "servlet-class"("com.vaadin.terminal.gwt.server.GrailsAwareApplicationServlet")
                            "init-param" {
                                    "description"("Vaadin application class to start")
                                    "param-name"("application")
                                    "param-value"(vaadinApplicationClass)
                }
                "load-on-startup"("1")
            }
        }

        def servletMappings = webXml."servlet-mapping"
        servletMappings[servletMappings.size() - 1] + {
                    "servlet-mapping" {
                            "servlet-name"("VaadinServlet")
                            "url-pattern"("/*")
            }
        }

        //println new StreamingMarkupBuilder().bind{ out << webXml };

    }

    def getConfig = {
        ClassLoader parent = getClass().getClassLoader();
        GroovyClassLoader loader = new GroovyClassLoader(parent);

        ConfigObject config;

        try {
            Class configFile = loader.loadClass(VAADIN_CONFIG_FILE);
            println("[Vaadin] Loading default config file: " + configFile + ".groovy ...");
            config = new ConfigSlurper().parse(configFile);
            println("[Vaadin] Loaded Vaadin config file:");
            println("[Vaadin]   -Production mode: " + config?.vaadin?.productionMode);
            println("[Vaadin]   -Application class: " + config?.vaadin?.applicationClass);
        } catch(ClassNotFoundException e) {
            println("[Vaadin] Did not find Vaadin plugin config file: " + VAADIN_CONFIG_FILE + ".groovy");
        }

        return config?.vaadin;
    }

    def doWithDynamicMethods = { ctx ->
        // TODO Implement registering dynamic methods to classes (optional)
    }

    def onChange = { event ->
        // TODO Implement code that is executed when any artefact that this plugin is
        // watching is modified and reloaded. The event contains: event.source,
        // event.application, event.manager, event.ctx, and event.plugin.
//        println(event.source)

    }

    def onConfigChange = { event ->
        // TODO Implement code that is executed when the project configuration changes.
        // The event is the same as for 'onChange'.
    }
}
